package iconSwingStates.Applications_Exemple.Paint;

import fr.lri.swingstates.canvas.CEllipse;
import fr.lri.swingstates.canvas.CRectangle;
import fr.lri.swingstates.canvas.CSegment;
import fr.lri.swingstates.canvas.CShape;
import fr.lri.swingstates.canvas.CText;
import fr.lri.swingstates.canvas.Canvas;
import fr.lri.swingstates.sm.State;
import fr.lri.swingstates.sm.Transition;
import iconSwingStates.StateMachine.SMIconStateMachine;
import iconSwingStates.Transitions.TDrag;
import iconSwingStates.Transitions.TRelease;
import iconSwingStates.Transitions.TransitionOnTag.TEnterOnTag;
import iconSwingStates.Transitions.TransitionOnTag.TLeaveOnTag;
import iconSwingStates.Transitions.TransitionOnTag.TPressOnTag;
import iconSwingStates.Transitions.TransitionOnTag.TTypedOnTag;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.geom.Point2D;

import javax.swing.JFrame;

/**
 * This class is a SwingStateMachine adapted to ICon.It's the graphic toolbox of the painting program.
 *@author uribe - gaget
 *
 */
public class SMPalette extends SMIconStateMachine{
	//final constant, use to build our graphic toolBox.
	private final int LARGEUR=70;
	private final int HAUTEUR=60;
	private final int ECART=1;
	private final int ST=LARGEUR+2*ECART;
	private final int BRUSH_MAX=30;
	
	private CEllipse blueButton,greenButton,alphaButton,redButton,brushButton,circleBrush;
	private CRectangle boutonLine,boutonCircle,boutonRect,colorPrev,brushPrev;
	public static CRectangle palette;
	private CShape useShape;
	public State init,drag;
	private CSegment alphaSegm,redSegm,greenSegm,blueSegm,brushSegm;
	private CText redText,greenText,blueText,alphaText;
	private int red=100;
	private int green=100;
	private int blue=100;
	private int alpha=255;

	public static int type=1;
	public static int brush=1;
	public static Color color;
	
	/**
	 * 
	 * @param name
	 * @param frame
	 * @param c
	 * @param pointer
	 */
	public SMPalette(String name,JFrame frame, Canvas c, String[] pointer) {
		super(name,frame,c,pointer);	
		init_interface(c);
		
		init = new State(){
			//Slide feedback transition
			Transition enterOntag = new TEnterOnTag("mouse1","slide"){
				public void action() {
					useShape=getShape();
					useShape.setFillPaint(Color.white);

				}
			};
			//Slide feedback transition
			Transition leaveOntag = new TLeaveOnTag("mouse1","slide"){
				public void action() {
					useShape.setFillPaint(Color.LIGHT_GRAY);
					useShape=null;
				}
			};
			//Slide use transition
			Transition pressOntag = new TPressOnTag("changeRGBA","mouse1",false,"slide",">> drag"){
			};
			
			//Click on the form's button, to change the type of drawing
			Transition clickOntagButton = new TTypedOnTag("changeForm","mouse1",false,"button"){
				public void action() {
					useShape=getShape();
					if(useShape != null){
						if (useShape.equals(boutonRect)){type=SMDraw.RECT;}
						else if (useShape.equals(boutonLine)){type=SMDraw.LINE;}
						else {type=SMDraw.CIRC;}
						majType();
					}
				}
			};
			
			//Form's button feedback.
			Transition enterOntagButton = new TEnterOnTag("mouse1","button",">>init"){
				public void action() {
					useShape=getShape();
					useShape.setFillPaint(Color.white);
				}
			};
			//Form's button feedback.
			Transition leaveOntagButton = new TLeaveOnTag("mouse1","button",">>init"){
				public void action() {
					useShape.setFillPaint(Color.LIGHT_GRAY);
					useShape=null;
				}
			};
		};
		drag = new State(){
			int[] test = {BOOLEAN};
			//Slide transitions
			Transition drag = new TDrag("selectRGBA","mouse1",test,false,false){
				public void action() {
					double x = getEvent().getX();
					double y = getEvent().getY();
					//If the tag is brush, the slide is to the top to the bottom, else the left to the right.
					if (useShape.hasTag("brush")){
						if (y<=brushSegm.getMaxY() && y>=brushSegm.getMinY())
							useShape.translateTo(useShape.getCenterX(),y);
						majBrush();						
					}else{
					if (x<=alphaSegm.getMaxX() && x>=alphaSegm.getMinX())
						useShape.translateTo(x, useShape.getCenterY());
					majColor();}
				}


			};
			Transition release = new TRelease("acceptChange","mouse1", false,">> init"){
				public void action() {
					useShape.setFillPaint(Color.LIGHT_GRAY);
				};
			};

		};
	};


	

	/**
	 * This function build a graphic toolbox into the canvas c. 
	 * @param c
	 */
	private void init_interface(Canvas c) {
		palette = new CRectangle(0,0,LARGEUR*15+ECART*10,HAUTEUR+2*ECART);

		//The form's button.
		boutonLine = new CRectangle(ECART, ECART, LARGEUR, HAUTEUR);
		boutonLine.setParent(palette);
		CSegment line =new CSegment(boutonLine.getMaxX()-LARGEUR/5,boutonLine.getMaxY()-HAUTEUR/5,boutonLine.getMinX()+LARGEUR/5,boutonLine.getMinY()+HAUTEUR/5);
		line.setParent(palette);

		boutonCircle = new CRectangle(ECART+ST, ECART, LARGEUR, HAUTEUR);
		boutonCircle.setParent(palette);
		CEllipse circle =new CEllipse(boutonCircle.getMinX()+LARGEUR/2-HAUTEUR/4,boutonCircle.getMinY()+HAUTEUR/2-HAUTEUR/4,HAUTEUR/2,HAUTEUR/2);
		circle.setParent(palette);

		boutonRect = new CRectangle(ECART+2*ST,  ECART, LARGEUR, HAUTEUR);
		boutonRect.setParent(palette);
		CRectangle rect =new CRectangle(boutonRect.getMinX()+LARGEUR/2-HAUTEUR/4,boutonRect.getMinY()+HAUTEUR/2-HAUTEUR/4,HAUTEUR/2,HAUTEUR/2);
		rect.setParent(palette);

		//The color's for
		CRectangle boutonColor = new CRectangle(ECART+3*ST,  ECART, 5*LARGEUR+8*ECART, HAUTEUR);
		boutonColor.setParent(palette);
			//the slide
		alphaSegm =new CSegment(boutonColor.getMaxX()-LARGEUR/10-2*LARGEUR,boutonColor.getMaxY()-HAUTEUR*1/5,boutonColor.getMinX()+LARGEUR/10,boutonColor.getMaxY()-HAUTEUR*1/5);
		alphaSegm.setParent(palette);
		blueSegm =new CSegment(boutonColor.getMaxX()-LARGEUR/10-2*LARGEUR,boutonColor.getMaxY()-HAUTEUR*2/5,boutonColor.getMinX()+LARGEUR/10,boutonColor.getMaxY()-HAUTEUR*2/5);
		blueSegm.setParent(palette);
		greenSegm =new CSegment(boutonColor.getMaxX()-LARGEUR/10-2*LARGEUR,boutonColor.getMaxY()-HAUTEUR*3/5,boutonColor.getMinX()+LARGEUR/10,boutonColor.getMaxY()-HAUTEUR*3/5);
		greenSegm.setParent(palette);
		redSegm =new CSegment(boutonColor.getMaxX()-LARGEUR/10-2*LARGEUR,boutonColor.getMaxY()-HAUTEUR*4/5,boutonColor.getMinX()+LARGEUR/10,boutonColor.getMaxY()-HAUTEUR*4/5);
		redSegm .setParent(palette);
		redButton =new CEllipse(redSegm.getMinX()-3,redSegm.getMinY()-3,7,7);
		redButton.setParent(palette);
		blueButton =new CEllipse(blueSegm.getMinX()-3,blueSegm.getMinY()-3,7,7);
		blueButton.setParent(palette);
		greenButton =new CEllipse(greenSegm.getMinX()-3,greenSegm.getMinY()-3,7,7);
		greenButton.setParent(palette);
		alphaButton =new CEllipse(alphaSegm.getMinX()-3,alphaSegm.getMinY()-3,7,7);
		alphaButton.setParent(palette);
			//color text
		Font f = new Font("Comic Sans MS",Font.BOLD,HAUTEUR/4);
		Point2D p = new Point2D.Double();
		p.setLocation(boutonColor.getMaxX()-2*LARGEUR,boutonColor.getMinY());
		redText= new CText(p,"red : 1.0",f);
		redText.setParent(palette);

		p.setLocation(boutonColor.getMaxX()-2*LARGEUR,boutonColor.getMinY()+HAUTEUR/4);
		greenText= new CText(p,"green : 1.0",f);
		greenText.setParent(palette);

		p.setLocation(boutonColor.getMaxX()-2*LARGEUR,boutonColor.getMinY()+HAUTEUR*2/4);
		blueText= new CText(p,"blue : 1.0",f);
		blueText.setParent(palette);

		p.setLocation(boutonColor.getMaxX()-2*LARGEUR,boutonColor.getMinY()+HAUTEUR*3/4);
		alphaText= new CText(p,"alpha : 255.0",f);
		alphaText.setParent(palette);

			//color outline
		colorPrev = new CRectangle(ECART+8*ST,  ECART, LARGEUR, HAUTEUR);
		colorPrev.setParent(palette);
		color=new Color(red,green,blue,alpha);	
		colorPrev.setFillPaint(color);

		//The brush's button
			//brush outline
		brushPrev = new CRectangle(ECART+9*ST,  ECART, LARGEUR, HAUTEUR);
		circleBrush = new CEllipse(ECART+9*ST+LARGEUR/2-brush/2, ECART+HAUTEUR/2-brush/2,brush,brush );
		circleBrush.setFillPaint(Color.black);
		
		brushPrev.setParent(palette);
		brush=1;	

		brushSegm =new CSegment(brushPrev.getMaxX()+ECART*2+LARGEUR/4,ECART*2,brushPrev.getMaxX()+ECART*2+LARGEUR/4,HAUTEUR-ECART);
		brushSegm.setParent(palette);
		
		brushButton =new CEllipse(brushSegm.getMinX()-3,brushSegm.getMinY()-3,7,7);
		brushButton.setParent(palette);

		//canvas adding.
		palette.addTo(c).addTag("notDrawable");
		boutonLine.addTo(c).addTag("line").setPickable(true).addTag("button").addTag("notDrawable");
		line.addTo(c).addTag("notDrawable");
		boutonCircle.addTo(c).addTag("circle").setPickable(true).addTag("button").addTag("notDrawable");
		circle.addTo(c).addTag("notDrawable");
		boutonRect.addTo(c).addTag("rect").setPickable(true).addTag("button").addTag("notDrawable");
		rect.addTo(c).addTag("notDrawable");
		boutonColor.addTo(c).addTag("notDrawable");
		redSegm.addTo(c).setPickable(false);
		greenSegm.addTo(c).setPickable(false);
		blueSegm.addTo(c).setPickable(false);
		alphaSegm.addTo(c).setPickable(false);
		brushSegm.addTo(c).setPickable(false);
		redButton.addTo(c).addTag("red").setPickable(true).addTag("slide").addTag("notDrawable");
		greenButton.addTo(c).addTag("green").setPickable(true).addTag("slide").addTag("notDrawable");
		blueButton.addTo(c).addTag("blue").setPickable(true).addTag("slide").addTag("notDrawable");
		alphaButton.addTo(c).addTag("alpha").setPickable(true).addTag("slide").addTag("notDrawable");
		brushButton.addTo(c).addTag("brush").setPickable(true).addTag("slide").addTag("notDrawable");
		
		redText.addTo(c).setPickable(false);
		greenText.addTo(c).setPickable(false);
		blueText.addTo(c).setPickable(false);
		alphaText.addTo(c).setPickable(false);
		colorPrev.addTo(c).setPickable(false);
		brushPrev.addTo(c).setPickable(false);
		circleBrush.addTo(c).setPickable(false);
		
		majType();
		majBoutonColor();
	}
	/**
	 * Color update
	 */
	public void majColor() {
		red=(int) Math.ceil((Math.abs(redSegm.getMinX()-redButton.getCenterX()))*255/redSegm.getLength());
		green=(int) Math.ceil((Math.abs(greenSegm.getMinX()-greenButton.getCenterX()))*255/greenSegm.getLength());
		blue=(int) Math.ceil((Math.abs(blueSegm.getMinX()-blueButton.getCenterX()))*255/blueSegm.getLength());
		alpha=(int) Math.ceil((Math.abs(alphaSegm.getMinX()-alphaButton.getCenterX()))*255/alphaSegm.getLength());
		if (red>255){red=255;};
		if (blue>255){blue=255;};
		if (green>255){green=255;};
		if (alpha>255){alpha=255;};
		redText.setText("red : "+red);		
		greenText.setText("green : "+green);
		blueText.setText("blue : "+blue);		
		alphaText.setText("alpha : "+alpha);
		color=new Color(red,green,blue,alpha);
		colorPrev.setFillPaint(color);
	}
	/**
	 * Brush size update. 
	 */
	public void majBrush() {
		brush=(int) Math.ceil((Math.abs(brushSegm.getMinY()-brushButton.getCenterY()))*BRUSH_MAX/brushSegm.getLength());
		if (brush==0){brush=1;}
		System.out.println(brush);
		getCanvas().removeShape(circleBrush);
		circleBrush = new CEllipse(ECART+9*ST+LARGEUR/2-brush/2, ECART+HAUTEUR/2-brush/2,brush,brush );
		circleBrush.setFillPaint(Color.black);
		circleBrush.addTo(getCanvas());
		
	}
	
	/**
	 * The Bouton Color position update
	 */
	public void majBoutonColor() {
		redButton.translateBy(Math.ceil(redSegm.getLength()*red/255), 0);
		blueButton.translateBy(Math.ceil(blueSegm.getLength()*blue/255), 0);
		greenButton.translateBy(Math.ceil(greenSegm.getLength()*green/255), 0);
		alphaButton.translateBy(Math.ceil(alphaSegm.getLength()*alpha/255), 0);
	}
	
	/**
	 * Drawing form update
	 */
	public void majType() {
		switch (type) {
		case SMDraw.CIRC: boutonCircle.setOutlinePaint(Color.BLUE).setStroke( new BasicStroke(2));
		boutonLine.setOutlinePaint(Color.BLACK).setStroke( new BasicStroke(1));
		boutonRect.setOutlinePaint(Color.BLACK).setStroke( new BasicStroke(1));		
		break;
		case SMDraw.LINE: boutonLine.setOutlinePaint(Color.BLUE).setStroke( new BasicStroke(2));
		boutonCircle.setOutlinePaint(Color.BLACK).setStroke( new BasicStroke(1));
		boutonRect.setOutlinePaint(Color.BLACK).setStroke( new BasicStroke(1));		
		break;

		case SMDraw.RECT: boutonRect.setOutlinePaint(Color.BLUE).setStroke( new BasicStroke(2));
		boutonLine.setOutlinePaint(Color.BLACK).setStroke( new BasicStroke(1));
		boutonCircle.setOutlinePaint(Color.BLACK).setStroke( new BasicStroke(1));		
		break;

		}
	}


	public int getAlpha() {
		return alpha;
	}

	public void setAlpha(int alpha) {
		this.alpha = alpha;
	}

	public int getBlue() {
		return blue;
	}

	public void setBlue(int blue) {
		this.blue = blue;
	}

	public Color getColor() {
		return color;
	}

	public void setColor(Color color) {
		this.color = color;
	}

	public int getGreen() {
		return green;
	}

	public void setGreen(int green) {
		this.green = green;
	}

	public int getRed() {
		return red;
	}

	public void setRed(int red) {
		this.red = red;
	}

}
